package com.dabao.interceptor;

import com.dabao.bean.Menu;
import com.dabao.service.RoleService;
import com.dabao.service.UserService;
import com.dabao.util.CacheUtils;
import com.dabao.util.CookieUtils;
import com.dabao.bean.User;
import com.dabao.util.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by dabao on 16/3/4.
 */
public class AdminInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private UserService userService;

    @Resource
    private RoleService roleService;

    @Resource
    private UserHolder userHolder;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        final String username = CookieUtils.getUsername(request);
        final String uri = request.getRequestURI();
        String permission;
        Pattern pattern = Pattern.compile("/admin/\\w+");
        Matcher matcher = pattern.matcher(uri);
        if(matcher.find()) {
            permission = matcher.group();
            if(permission.equalsIgnoreCase("/admin/login")
                    || permission.equalsIgnoreCase("/admin/logout")){
                return true;
            }

            if(!CookieUtils.hasLogin(request)) {
                response.sendRedirect("/admin/login");
                return false;
            }

            final User user = (User) CacheUtils.get(username, new Callable() {
                public Object call() throws Exception {
                    return userService.findByUsername(username);
                }
            });

            if(user == null) {
                response.sendRedirect("/admin/login");
                return false;
            }

            Set<String> permissions = (Set<String>) CacheUtils.get(username + "_permissions", new Callable() {
                public Object call() throws Exception {
                    List<Menu> menus = roleService.selectMenus(user.getRoleId());
                    return permissions(menus);
                }
            });

            List<Menu> menus = (List<Menu>) CacheUtils.get(username + "_menus", new Callable() {
                public Object call() throws Exception {
                    List<Menu> menus = roleService.selectMenus(user.getRoleId());
                    return menuTree(menus);
                }
            });
            user.setMenus(menus);

            if(!permissions.contains(permission+"/")) {
                return false;
            }

            request.setAttribute("menus", menus);
            request.setAttribute("justPath", uri);
            request.setAttribute("user", user);
            userHolder.setUser(user);
        }

        else {
            response.sendRedirect("/admin/login");
            return false;
        }
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        userHolder.remove();
    }

    /**
     * 菜单分为一级目录和二级目录
     * 将二级目录的元素放到一级目录的children中
     * @param menus
     * @return
     */
    private List<Menu> menuTree(List<Menu> menus) {
        List<Menu> firstLevels =  new ArrayList<Menu>();

        for(Menu menu : menus) {
            if(menu.getType() == 0) {
                menu.setChildren(new ArrayList<Menu>());
                firstLevels.add(menu);
            }
        }

        for(Menu menu : menus)
            for (Menu firstLevel : firstLevels) {
                if(firstLevel.getId() == menu.getParentId()) {
                    firstLevel.getChildren().add(menu);
                }
            }
        return firstLevels;
    }

    /**
     * 权限
     * @param menus
     * @return
     */
    public Set<String> permissions(List<Menu> menus) {
        Set<String> permissions = new HashSet<String>();
        for(Menu menu : menus) {
            if(StringUtils.isNotBlank(menu.getUrl())) {
                permissions.add(menu.getUrl());
            }
        }
        permissions.add("/admin/index/");
        permissions.add("/admin/imageUp/");
        return permissions;
    }
}
